<?php
// +----------------------------------------------------------------------
// | 麦沃德科技赋能开发者，助力中小企业发展
// +----------------------------------------------------------------------
// | Copyright (c) 2017～2024  www.wdadmin.cn    All rights reserved.
// +----------------------------------------------------------------------
// | Wdadmin系统产品软件并不是自由软件，不加密，并不代表开源，未经许可不可自由转售和商用
// +----------------------------------------------------------------------
// | Author: MY WORLD Team <bd@maiwd.cn>   www.wdadmin.cn
// +----------------------------------------------------------------------
/**
 * Class Order
 * Desc  代驾订单控制器
 * Create on 2024/10/22 15:15
 * Create by wangyafang
 */

namespace app\api\controller\wddj\trailer;


use app\api\controller\wddj\user\Map;
use app\api\model\wddj\Chat;
use app\api\model\wddj\trailer\CancellationLogs;
use app\api\model\wddj\trailer\CommissionRatio;
use app\api\model\wddj\trailer\Driver;
use app\api\model\wddj\trailer\OperationConfig;
use app\api\model\wddj\User;
use app\api\model\wddj\user\operation\CostAllocation;
use app\api\model\wddj\user\Passenger;
use app\api\model\wddj\user\Payments;
use app\api\model\wddj\user\Refunds;
use app\api\model\wddj\user\UserRealNameAuthentication;
use app\api\model\wddj\WaitingTime;
use app\common\controller\Api;
use think\Db;
use Exception;
use think\exception\PDOException;
use think\exception\ValidateException;
use app\admin\model\disassemble\Order as BackOrder;

class Order extends Api
{
    protected $noNeedLogin = [''];
    protected $noNeedRight = ['*'];
    protected $model = null;
    protected $wechat_id = null;
    protected $driverObj = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\api\model\wddj\trailer\Order();
        $wechat_id = User::getWechatId($this->auth->id);
        $driverObj = (new \app\api\model\wddj\trailer\Driver())->where('wechat_id',$wechat_id)->find();
        if (!$driverObj) {
            $this->error('不是司机，没有权限');
        }
        $this->wechat_id = $wechat_id;
        $this->driverObj = $driverObj;
    }

    /**
     * Desc 订单列表
     * Create on 2024/10/22 15:15
     * Create by wangyafang
     */
    public function index()
    {
        if(!$this->request->isGet()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->get();

        if (isset($param['state']) && !empty($param['state'])) {
            if ($param['state'] == 'completed') {
                $where['state'] = array('in',array('adjusting','refunded','awaiting_payment','completed'));
            } else {
                $where['state'] = array('eq',$param['state']);
            }
        }

        $where['driver_wechat_id'] = array('eq',$this->wechat_id);
        $page = isset($param['page']) ? $param['page'] : '';
        $limit = isset($param['limit']) ? $param['limit'] : 10;
        $count = $this->model->where($where)->count();
        $order = 'id desc';

        $data = $this->model
            ->where($where)
            ->page($page,$limit)
            ->field('id,departure_time,state,actual_amount,from_address,to_address,type,driver_arrive_status,city_id')
            ->order($order)
            ->select();

        foreach ($data as &$v) {

//            $driver_commission_ratio = (new CommissionRatio())->where('city_id',$v['city_id'])->field('driver_commission_ratio')->find();
//            $driver_commission_ratio = bcdiv($driver_commission_ratio['driver_commission_ratio'],100,2);
//            $v->actual_amount = bcmul($v->actual_amount,$driver_commission_ratio,2);
            if (in_array($v->state,array('adjusting','refunded','awaiting_payment'))) {
                $v->state = 'completed';
            }



        }

        $this->success('请求成功',['total'=>$count,'data'=>$data]);
    }

    /**
     * Desc 抢单列表
     * Create on 2024/11/29 11:25
     * Create by wangyafang
     */
    public function grab_list()
    {
        if (!$this->request->isGet()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->get();

        // 获取经度和纬度并进行验证
        $lng = $this->driverObj->driver_lng;
        $lat = $this->driverObj->driver_lat;

        // 验证经度和纬度是否为空
        if (empty($lng) || empty($lat)) {
            $this->error('居住地异常');
        }

        // 过滤并转换为浮动数值
        $lng = floatval($lng);
        $lat = floatval($lat);

        // 验证经度和纬度是否在有效范围内
        if ($lng < -180 || $lng > 180) {
            $this->error('经度值不在有效范围内');
        }
        if ($lat < -90 || $lat > 90) {
            $this->error('纬度值不在有效范围内');
        }

        // 设置查询条件：使用闭包构建 OR 条件
        $where = function($query) {
            // 回收订单条件：is_check=0, state=unpaid, is_back_agree=1
            $query->where([
//                'is_check' => 0,
                'state' => 'unpaid',
                'is_back_agree' => 1
            ])->whereOr([
                // 检测订单条件：is_check=1, state=pending
//                'is_check' => 1,
                'state' => 'pending'
            ]);
        };

        // 获取分页和限制参数
        $page = isset($param['page']) ? $param['page'] : 1;
        $limit = isset($param['limit']) ? $param['limit'] : 10;

        // 地球半径 (单位：公里)
        $earthRadius = 6371;
        $radius = (new OperationConfig())->where('id', 1)->value('driver_kilometer');

        // 构建查询条件（计算距离）
        $distanceCondition = DB::raw(
            "($earthRadius * ACOS(
            COS(RADIANS($lat)) * COS(RADIANS(from_lat)) * 
            COS(RADIANS(from_lng) - RADIANS($lng)) + 
            SIN(RADIANS($lat)) * SIN(RADIANS(from_lat))
        )) < $radius"
        );

        // 获取符合条件的总数
        $count = $this->model
            ->where($where)
            ->where($distanceCondition) // 使用计算出来的距离条件
            ->count();

        // 获取分页数据
        $data = $this->model
            ->where($where)
            ->where($distanceCondition) // 使用计算出来的距离条件
            ->page($page, $limit)
            ->field('id,city_id,departure_time,actual_amount,state,pay_amount,from_address,to_address,type,from_lat,from_lng,is_back_agree, (
            ' . $earthRadius . ' * ACOS(
                COS(RADIANS(' . $lat . ')) * COS(RADIANS(from_lat)) * 
                COS(RADIANS(from_lng) - RADIANS(' . $lng . ')) + 
                SIN(RADIANS(' . $lat . ')) * SIN(RADIANS(from_lat))
            )
        ) AS distance')
            ->order('distance', 'asc')
            ->select();

        // 处理每条数据
        foreach ($data as $v) {
            $v->hidden(['from_lat', 'from_lng']);

            // 获取司机的佣金比率
//            $driver_commission_ratio = (new CommissionRatio())->where('city_id', $v['city_id'])->field('driver_commission_ratio')->find();
//            if ($driver_commission_ratio) {
//                $driver_commission_ratio = bcdiv($driver_commission_ratio['driver_commission_ratio'], 100, 2);
//                $v->actual_amount = bcmul($v->actual_amount, $driver_commission_ratio, 2);
//            }
        }

        // 返回成功响应
        $this->success('请求成功', ['total' => $count, 'data' => $data]);
    }



    /**
     * Desc 详情
     * Create on 2024/10/22 15:16
     * Create by wangyafang
     */
    public function details()
    {
        if(!$this->request->isGet()) {
            $this->error('请求类型错误');
        }
        $id = $this->request->get('id');
        if (empty($id)) {
            $this->error('请输入订单ID');
        }
        $orderObj = $param = $this->model->get($id);

        $orderNewObj = $this->model->get($id);

        $data = array();

        switch ($orderObj['state']) {
            case 'pending'://待接单
                $estimated_time = \app\api\model\wddj\user\Order::acceptanceDetails($orderObj);
                $mapResult = (new Map())->get_driver_routes($param);
                $routes = $mapResult['result']['routes'];
                if (!empty($orderObj['passenger_id'])) {
                    $passengerObj = (new Passenger())->get($orderObj['passenger_id']);
                    $userWechatObj = (new \app\api\model\wddj\UserWechat())->get($orderObj['wechat_id']);
                    $passenger_info = array(
                        'name'=>$passengerObj['name'],
                        'mobile'=>substr_replace($passengerObj['mobile'], '*****', 3, -3),
                        'avatar'=>wddj_full_url($userWechatObj['avatar']),
                    );
                } else {
                    $userRealNameAuthenticationName = (new UserRealNameAuthentication())->where('wechat_id',$orderObj['wechat_id'])->value('name');
                    $userWechatObj = (new \app\api\model\wddj\UserWechat())->get($orderObj['wechat_id']);
                    $passenger_info = array(
                        'name'=>'',
                        'mobile'=>substr_replace($userWechatObj['mobile'], '*****', 3, -3),
                        'avatar'=>wddj_full_url('/assets/addons/wddj/img/user.png'),
                    );
                }
                $data = array(
                    'from_address'=>$orderObj['from_address'],
                    'to_address'=>$orderObj['to_address'],
                    'estimated_time'=>$estimated_time,
                    'pay_amount'=>$orderObj['pay_amount'],
                    'passenger_info'=> $passenger_info,
                    'remarks'=>$orderObj['remarks'],
                    'state'=>$orderObj['state'],
                    'routes'=>$routes,
                );
                break;
            case 'accepted'://已接单
                $passenger_info = $this->get_passenger($orderObj);
                $driverObj = (new Driver())->get($orderObj['driver_id']);
                $paramMap['from_lat'] = $driverObj['driver_lat'];
                $paramMap['from_lng'] = $driverObj['driver_lng'];
                $paramMap['to_lat'] = $orderObj['from_lat'];
                $paramMap['to_lng'] = $orderObj['from_lng'];
                $mapResult = (new Map())->get_driver_routes($paramMap);
                $routes = $mapResult['result']['routes'];
                $data = array(
                    'from_address'=>$orderObj['from_address'],
                    'to_address'=>$orderObj['to_address'],
                    'departure_time'=>$orderObj['departure_time'],
                    'passenger_info'=> $passenger_info,
                    'remarks'=>$orderObj['remarks'],
                    'state'=>$orderObj['state'],
                    'routes'=>$routes,
                    'waiting_start_time'=> $orderObj['arrive_time']
                );
                break;
            case 'in_progress'://行驶中
                $paramMap['from_lat'] = $this->request->get('driver_lat');
                if (empty($paramMap['from_lat'])) {
                    $this->error('司机纬度不能为空');
                }
                $paramMap['from_lng'] = $this->request->get('driver_lng');
                if (empty($paramMap['from_lng'])) {
                    $this->error('司机经度不能为空');
                }
                $paramMap['to_lat'] = $orderObj['to_lat'];
                $paramMap['to_lng'] = $orderObj['to_lng'];
                $mapResult = (new Map())->get_driver_routes($paramMap);
                $routes = $mapResult['result']['routes'];
                $passenger_info = $this->get_passenger($orderObj);
                $data = array(
                    'passenger_info'=> $passenger_info,
                    'from_address'=>$orderObj['from_address'],
                    'to_address'=>$orderObj['to_address'],
                    'departure_time'=>$orderObj['departure_time'],
                    'remarks'=>$orderObj['remarks'],
                    'state'=>$orderObj['state'],
                    'actual_kilometer'=>bcdiv($orderObj['actual_amount'],1000,2),
                    'actual_amount'=>$orderObj['actual_amount'],
                    'routes'=>$routes,
                    'waiting_start_time'=> (new WaitingTime())->where('order_id',$id)->where('type','waiting_midway')->where('end_time',0)->order('id desc')->limit(1)->value('start_time')
                );
                break;
            case 'adjusting'://行驶结束
            case 'refunded'://行驶结束
            case 'awaiting_payment'://行驶结束
            case 'completed'://行驶结束
                $mapResult = (new Map())->get_driver_routes($param);
                $routes = $mapResult['result']['routes'];
                $mobile = (new \app\api\model\wddj\UserWechat())->where('id',$orderObj['wechat_id'])->value('mobile');
                $data = array(
                    'pay_amount'=>$orderObj['pay_amount'],
                    'state'=>'completed',
                    'routes'=>$routes,
                    'waiting_start_time'=> (new WaitingTime())->where('order_id',$id)->where('type','waiting_midway')->where('end_time',0)->order('id desc')->limit(1)->value('start_time'),
                    'order_no'=>$orderObj['order_no'],
                    'avatar'=>wddj_full_url('/assets/addons/wddj/img/user.png'),
                    'mobile'=>'**'.substr($mobile, -2),
                    'from_address'=>$orderObj['from_address'],
                    'to_address'=>$orderObj['to_address'],
                    'arrive_time'=>date('Y-m-d H:i',$orderObj['arrive_time']),
                );
                break;
        }
        $data['driver_arrive_status'] = $orderObj['driver_arrive_status'];
        $data['departure_time'] = $orderObj['departure_time'];
        $data['from_lat'] =$orderNewObj['from_lat'];
        $data['from_lng']=$orderNewObj['from_lng'];
        $data['to_lat']=$orderNewObj['to_lat'];
        $data['to_lng']=$orderNewObj['to_lng'];

//        $commissionRatioObj = (new CommissionRatio())->where('city_id',$orderObj['city_id'])->find();
//        $driver_percent_pay_amount = bcmul($orderObj['actual_amount'],$commissionRatioObj['driver_commission_ratio'],2);
//        $data['actual_amount'] = bcdiv($driver_percent_pay_amount,100,2);
        $this->success('请求成功',$data);
    }

    protected function get_passenger($orderObj)
    {
        if (!empty($orderObj['passenger_id'])) {
            $avatar = '/assets/addons/wddj/img/user.png';
            $passengerObj = (new Passenger())->get($orderObj['passenger_id']);
            $passenger_info = array(
                'mobile'=>substr_replace($passengerObj['mobile'], '*****', 3, -3),
                'fictitious_mobile'=>$passengerObj['mobile'],
                'avatar'=>wddj_full_url($avatar),
                //todo 虚拟手机号
            );
        } else {
            $userWechatObj = (new \app\api\model\wddj\UserWechat())->get($orderObj['wechat_id']);
            $passenger_info = array(
                'mobile'=>substr_replace($userWechatObj['mobile'], '*****', 3, -3),
                'fictitious_mobile'=>$userWechatObj['mobile'],
                'avatar'=>wddj_full_url($userWechatObj['avatar']),
                //todo 虚拟手机号
            );
        }
        return $passenger_info;
    }


    /**
     * Desc 抢单
     * Create on 2024/10/22 15:17
     * Create by wangyafang
     */
    public function grab_orders()
    {
        if(!$this->request->isPost()) {
            $this->error('请求类型错误');
        }
        if ($this->driverObj->order_status == '2') {
            $this->error('休息时间不可接单');
        }
        if ($this->driverObj->status == 'hidden') {
            $this->error('接单功能被禁用,请联系管理员解禁');
        }
        if ($this->driverObj->is_vehicle == 0) {
            $this->error('请先录入车辆信息');
        }
        $id = $this->request->post('id');
        $estimated_amount = $this->request->post('estimated_amount');
        $driving_distance = $this->request->post('driving_distance');
        $driving_image = $this->request->post('driving_image');
        $orderObj = (new \app\api\model\wddj\trailer\Order())->cache(3600)->find($id);

        $acceptance_order_count = cache('id'.$id.'cityId'.$orderObj['city_id'].'orderNo'.$orderObj['order_no']);
        if ($acceptance_order_count) {
            $this->error('订单被接了');
        }


        if($orderObj->driver_wechat_id == $this->wechat_id) {
            $this->error('已经接这个单了');
        }
        if (in_array($orderObj['state'],['accepted','in_progress','adjusting','refunded','awaiting_payment','completed'])) {
            $this->error('订单已被其他司机接过了');
        }
        $cancellationLogsCount = (new CancellationLogs())
            ->whereTime('cancel_time', 'today')
            ->where('driver_id',$this->driverObj->id)
            ->where('wechat_id',$this->driverObj->wechat_id)
            ->count();
        $driverCancelCount = (new OperationConfig())->where('id',1)->value('driver_cancel_count');
        if ($cancellationLogsCount >= $driverCancelCount) {
            $this->error('订单取消次数超过当日限制，今日不可接单，明天恢复');
        }

        $update_data = array(
            'state'=>'accepted',
            'acceptance_time'=>date('Y-m-d H:i:s',time()),
            'driver_id'=>$this->driverObj->id,
            'driver_wechat_id'=>$this->driverObj->wechat_id,
        );
        $mapResult = (new Map())->get_driver_routes([
            'from_lat'=>$this->driverObj->driver_lat,
            'from_lng'=>$this->driverObj->driver_lng,
            'to_lat'=>$orderObj->from_lat,
            'to_lng'=>$orderObj->from_lng
        ]);
        $update_data['begintime'] = strtotime("-{$mapResult['result']['routes'][0]['duration']} minutes {$orderObj['departure_time']}");
        $driverAcceptOtherOrderCount = $this->model->where('driver_id',$this->driverObj->id)
            ->where(['begintime'=>['<=',$update_data['begintime']],'end_time'=>['>=',$update_data['begintime']]])
            ->where('state','in',['accepted','in_progress'])
            ->count();
        $driverAcceptOtherOrderCountEnd = $this->model->where('driver_id',$this->driverObj->id)
            ->where(['begintime'=>['<=',$orderObj['end_time']],'end_time'=>['>=',$orderObj['end_time']]])
            ->where('state','in',['accepted','in_progress'])
            ->count();
        if($driverAcceptOtherOrderCount > 0 || $driverAcceptOtherOrderCountEnd > 0) {
            $this->error('已接其他乘车单，请先完成，再接单');
        }

        $result = false;
        Db::startTrans();
        try {
            $updateOrderObj = $this->model->lock(true)->find($orderObj['id']);
//            if($orderObj->is_check == 0 && $orderObj->is_back_agree == 1)
            if($orderObj->is_back_agree == 1)
            {
                //回收订单--抢单报价
                $update_data['estimated_amount'] = $estimated_amount;
                $update_data['actual_amount'] = $estimated_amount;
                $update_data['pay_amount'] = $estimated_amount;
                $update_data['is_back_agree'] = 2;
                //厂商报价确认后需要将这个车费加到end_price
                $BackOrder = BackOrder::where(['tuoche_trade_no'=>$orderObj->order_no])->update(['tuoche_amount'=>$estimated_amount,'tuoche_distance'=>$driving_distance,'tuoche_image'=>$driving_image,'carer_status'=>1]);

            }
            $result = $updateOrderObj->save($update_data);
            //将车牌号同步给回收订单
            db('back_order')->where(['tuoche_trade_no'=>$updateOrderObj->order_no])->update(['tuoche_plate'=>(db('vehicle')->where(['wechat_id'=>$this->wechat_id])->value('plate_number'))]);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if (false === $result) {
            $this->error('抢单失败');
        } else {
            cache('id'.$id.'cityId'.$orderObj['city_id'].'orderNo'.$orderObj['order_no'],1,3600);
            $this->success('抢单成功');
        }
    }

    /**
     * Desc 取消订单
     * Create on 2024/10/22 15:18
     * Create by wangyafang
     */
    public function cancel()
    {
        $this->error('不可取消订单');
        if(!$this->request->isPost()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->post();
        $result = $this->validate($param,'app\api\validate\wddj\trailer\Order.cancel');
        if(true !== $result){
            // 验证失败 输出错误信息
            $this->error($result);
        }
        $id = $param['id'];
        $orderObj = $this->model->get($id);
        if($orderObj->driver_wechat_id != $this->wechat_id) {
            $this->error('不是自己接的单，无法操作');
        }
        if ($orderObj['state'] != 'accepted') {
            $this->error('不是已接单状态，无法操作');
        }
        if ($orderObj['state'] == 'cancelled') {
            $this->error('已取消订单');
        }
        if ($orderObj['is_back_agree'] != 3) {
            $this->error('请等待厂商确认报价');
        }

        $cancel_time = date('Y-m-d H:i:s',time());
        $result = false;
        Db::startTrans();
        try {
            $update_data = array(
                'state'=>'pending',
                'cancel_time'=>$cancel_time,
                'driver_id'=>'',
                'driver_wechat_id'=>'',
                'begintime'=>0,
                'estimated_amount'=>0,
                'actual_amount'=>0,
                'pay_amount'=>0,
                'is_back_agree'=>1,
            );
            $result = $orderObj->save($update_data);

            $cancellation_logs_data = array(
                'order_id'=>$orderObj['id'],//订单id
                'wechat_id'=>$this->driverObj->wechat_id,
                'driver_id'=>$this->driverObj->id,
                'cancel_time'=>$cancel_time,
            );
            $cancellationLogsModel = new CancellationLogs();
            $cancellationLogsModel->data($cancellation_logs_data);
            $cancellationLogsModel->allowField(true)->save();
            (new Chat())->where('order_id',$id)->where('driver_wechat_id',$this->wechat_id)->delete();
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if (false === $result) {
            $this->error('取消订单失败');
        }
        cache('id'.$id.'cityId'.$orderObj['city_id'].'orderNo'.$orderObj['order_no'],null);
        $this->success('取消订单成功');
    }

    /**
     * Desc 我已到达
     * Create on 2024/11/29 16:45
     * Create by wangyafang
     */
    public function arrived()
    {
        if(!$this->request->isPost()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->post();

        $id = $param['id'];
        $orderObj = $this->model->get($id);
        if (!$orderObj) {
            $this->error('订单不存在');
        }

        if($orderObj->driver_wechat_id != $this->wechat_id) {
            $this->error('不是自己接的单，无法操作');
        }


        if ($orderObj['state'] != 'accepted') {
            $this->error('不是已接单状态，无法操作');
        }

        if ($orderObj['driver_arrive_status'] == 'arrived') {
            $this->error('已点击到达');
        }
        if ($orderObj['is_back_agree'] != 3) {
            $this->error('请等待厂商确认报价');
        }

        $arrive_kilometer = (new OperationConfig())->where('id',1)->value('arrive_kilometer');
        $mapParam = array(
            'from_lat'=>$param['lat'],
            'from_lng'=>$param['lng'],
            'to_lat'=>$orderObj['from_lat'],
            'to_lng'=>$orderObj['from_lng'],
        );
        $mapResult = (new Map())->get_driver_routes($mapParam);
        $calculationMetre = $mapResult['result']['routes'][0]['distance'];
        if ($calculationMetre > $arrive_kilometer) {
            $this->error('距离用户出发地超过'.$arrive_kilometer.'米，无法操作');
        }

        $update_data = array(
            'driver_arrive_status'=>'arrived',
            'arrive_time'=>time(),
        );
        $result = false;
        Db::startTrans();
        try {
            $result = $orderObj->save($update_data);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if (false === $result) {
            $this->error('我已到达操作失败');
        }

        $this->success('我已到达操作成功');
    }

    /**
     * Desc 开始行程
     * Create on 2024/10/22 15:18
     * Create by wangyafang
     */
    public function start_itinerary()
    {
        if(!$this->request->isPost()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->post();
        $result = $this->validate($param,'app\api\validate\wddj\trailer\Order.start_itinerary');
        if(true !== $result){
            // 验证失败 输出错误信息
            $this->error($result);
        }
        $id = $param['id'];
        $tail_number = $param['tail_number'];
        $departure_images = $param['departure_images'];
        $file_status = $param['file_status'];
        $file_desc = $param['file_desc'];
        $orderObj = $this->model->get($id);
        if (!$orderObj) {
            $this->error('订单不存在');
        }

        if($orderObj->driver_wechat_id != $this->wechat_id) {
            $this->error('不是自己接的单，无法操作');
        }
        if (in_array($orderObj['state'],['in_progress','adjusting','refunded','awaiting_payment','completed'])) {
            $this->error('已确认上车');
        }
        if ($orderObj['state'] != 'accepted') {
            $this->error('不是已接单状态，无法操作');
        }
        $mobile = \app\api\model\wddj\trailer\Order::getMobile($orderObj->toArray());
        $mobile_tail_number = substr($mobile,-4);
        if ($tail_number != $mobile_tail_number) {
            $this->error('手机尾号4位数不正确');
        }

        $update_data = array(
            'state'=>'in_progress',
            'confirm_boarding_time'=>date('Y-m-d H:i:s',time()),
            'departure_images'=>$departure_images,
        );
        $result = false;
        Db::startTrans();
        try {
            $result = $orderObj->save($update_data);
            db('back_order')->where(['out_trade_no'=>$orderObj->order_no])->update(['file_status'=>$file_status,'file_desc'=>$file_desc]);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if (false === $result) {
            $this->error('确认已上车失败');
        }

        $current_time = time();
        $waiting_time_minute = wddj_get_waiting_time($current_time,$orderObj['arrive_time']);
        $free_waiting_time = (new CostAllocation())->where('city_id',$orderObj['city_id'])->value('free_waiting_time');
        if ($waiting_time_minute > $free_waiting_time) {
            $waiting_time_data = array(
                'order_id'=>$orderObj['id'],
                'type'=>'arrived',
                'free_waiting_time'=>$free_waiting_time,
                'end_time'=>$current_time,
                'start_time'=>$orderObj['arrive_time'],
                'minute'=>bcsub($waiting_time_minute,$free_waiting_time),
            );
            $waitingTimeModel = new WaitingTime();
            $waitingTimeModel->data($waiting_time_data);
            $waitingTimeModel->allowField(true)->save();
        }
        cache('orderId'.$orderObj['id'].'orderNo'.$orderObj['order_no'].'driverId'.$this->driverObj->id.'acceptanceTime'.$orderObj['acceptance_time'],NULL);
        $this->success('确认已上车成功');
    }

    /**
     * Desc 到达目的地
     * Create on 2024/10/22 15:21
     * Create by wangyafang
     */
    public function arrive_at_destination()
    {
        if(!$this->request->isPost()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->post();
        $result = $this->validate($param,'app\api\validate\wddj\trailer\Order.arrive_at_destination');
        if(true !== $result){
            // 验证失败 输出错误信息
            $this->error($result);
        }
        $id = $param['id'];
        $orderObj = $this->model->get($id);

        if (!$orderObj) {
            $this->error('订单不存在');
        }

        if($orderObj->driver_wechat_id != $this->wechat_id) {
            $this->error('不是自己接的单，无法操作');
        }
        if (in_array($orderObj['state'],['adjusting','refunded','awaiting_payment','completed'])) {
            $this->error('行程已结束');
        }
        if ($orderObj['state'] != 'in_progress') {
            $this->error('不是行驶中状态，无法操作');
        }
        $mapParam = array(
            'from_lat'=>$param['lat'],
            'from_lng'=>$param['lng'],
            'to_lat'=>$orderObj['to_lat'],
            'to_lng'=>$orderObj['to_lng'],
        );
        $to_destination_range_switch = (new OperationConfig())->where('id',1)->value('to_destination_range_switch');
        if ($to_destination_range_switch == 'normal') {
            $mapResult = (new Map())->get_driver_routes($mapParam);
            $calculationMetre = $mapResult['result']['routes'][0]['distance'];
            $to_destination_range_metre = (new OperationConfig())->where('id',1)->value('to_destination_range_metre');
            if ($calculationMetre > $to_destination_range_metre) {
                $this->error('距离目的地超过'.$to_destination_range_metre.'米，无法操作');
            }
        }


        $commissionRatioObj = (new CommissionRatio())->where('city_id',$orderObj['city_id'])->find();
        if (empty($commissionRatioObj)) {
            $this->error('城市未配置抽成比例，无法到达目的地');
        }
        $actual_total_meter = (new \app\api\model\wddj\trailer\DistanceCalculations())
            ->where('order_id',$orderObj['id'])
            ->sum('meter');
        $actual_amount = CostAllocation::get_actual_amount($orderObj['id'],$orderObj['actual_amount']);

        $percent_pay_amount = bcdiv($actual_amount['estimated_amount'],100,2);
        $platform_commission = bcmul($percent_pay_amount,$commissionRatioObj['platform_commission_ratio'],2);
        if ($orderObj['estimated_amount'] == $actual_amount['estimated_amount']) {
            $update_data = array(
                'state'=>'completed',
                'completion_time'=>date('Y-m-d H:i:s',time()),
                'actual_amount'=>$actual_amount['estimated_amount'],
                'adjust_amount'=>0,
                'platform_commission'=>$platform_commission,
                'actual_meter'=>$actual_total_meter,
            );
        } elseif($orderObj['estimated_amount'] > $actual_amount['estimated_amount']) {//多退
            $update_data = array(
                'state'=>'adjusting',
                'actual_amount'=>$actual_amount['estimated_amount'],
                'adjust_amount'=>bcsub($orderObj['estimated_amount'],$actual_amount['estimated_amount'],2),
                'platform_commission'=>$platform_commission,
                'actual_meter'=>$actual_total_meter,
            );
        } else {//少补
            $update_data = array(
                'state'=>'adjusting',
                'actual_amount'=>$actual_amount['estimated_amount'],
                'adjust_amount'=>bcsub($orderObj['estimated_amount'],$actual_amount['estimated_amount'],2),
                'platform_commission'=>$platform_commission,
                'actual_meter'=>$actual_total_meter,
            );
        }
        $driver_percent_pay_amount = bcmul($actual_amount['estimated_amount'],$commissionRatioObj['driver_commission_ratio'],2);
        $driver_commission = bcdiv($driver_percent_pay_amount,100,2);

        $platform_percent_pay_amount = bcmul($actual_amount['estimated_amount'],$commissionRatioObj['platform_commission_ratio'],2);
        $platform_commission = bcdiv($platform_percent_pay_amount,100,2);

        $update_data['driver_commission'] = $driver_commission;//confirm_boarding_time
        $update_data['arrive_images'] = $param['arrive_images'];
        $result = false;
        Db::startTrans();
        try {
            $result = $orderObj->save($update_data);
            $update_driver_balance = bcadd($this->driverObj->balance,$driver_commission,2);
            $driverObj = (new Driver())->lock(true)->find($this->driverObj->id);
            $driverObj->balance = $update_driver_balance;
            $driverObj->save();
            $list = [
                array(
                    'city_id'=>$orderObj['city_id'],
                    'wechat_id'=>$this->driverObj->wechat_id,
                    'driver_id'=>$this->driverObj->id,
                    'title'=>'完成订单',
                    'operate'=>'1',//操作：增加金额
                    'amount'=>$driver_commission,
                    'order_id'=>$orderObj['id'],//订单id
                    'group_type'=>'1',//司机师傅
                ),
                array(
                    'city_id'=>$orderObj['city_id'],
                    'wechat_id'=>$this->driverObj->wechat_id,
                    'driver_id'=>$this->driverObj->id,
                    'title'=>'完成订单',
                    'operate'=>'1',//操作：增加金额
                    'amount'=>$platform_commission,
                    'order_id'=>$orderObj['id'],//订单id
                    'group_type'=>'2',//平台
                ),
            ];
            $incomeExpenditureModel = new \app\api\model\wddj\trailer\IncomeExpenditure();
            $incomeExpenditureModel->saveAll($list);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if (false === $result) {
            $this->error('到达目的地失败');
        }

        if ($update_data['adjust_amount'] > 0) {//多退
            $refunded_result = false;
            $refund_no = wddj_create_order();
            $refundsModel = new Refunds();
            Db::startTrans();
            try {
                $refunded_result = $orderObj->save(array(
                    'state'=>'refunded',
                    'adjust_state'=>'refund',
                ));
                $refund_data = array(
                    'order_id'=>$id,
                    'refund_amount'=>$update_data['adjust_amount'],
                    'refund_no'=>$refund_no,
                    'refund_time'=>time(),
                    'reason'=>'实际费用低于预估费用,退款',
                    'refund_status'=>'pending',
                );
                $refundsModel->data($refund_data);
                $refundsModel->allowField(true)->save();
                Db::commit();
            } catch (ValidateException|PDOException|Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }

            if ($refunded_result != false && ($orderObj['pay_amount'] > $update_data['actual_amount'])) {
                $res=\addons\wddj\library\Wxapp::payRefund($orderObj->order_no,$refund_no,$update_data['adjust_amount'],array('refund_desc'=>'实际费用低于预估费用,退款'));
                if($res && $res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS'){
                    Db::startTrans();
                    try {
                        $orderObj->save(array(
                            'state'=>'completed',
                            'pay_amount'=>$update_data['adjust_amount'],
                            'completion_time'=>date('Y-m-d H:i:s',time()),
                        ));
                        $refundsObj = $refundsModel->where('order_id',$id)->find();
                        $refundsObj->save(
                            array(
                                'refund_status'=>'completed',
                            )
                        );
                        Db::commit();
                    } catch (ValidateException|PDOException|Exception $e) {
                        Db::rollback();
                        $this->error($e->getMessage());
                    }
                }else{
                    $refundsObj = $refundsModel->where('order_id',$id)->find();
                    $refundsObj->save(
                        array(
                            'refund_status'=>'failed',
                            'failed_reason'=>$res['return_msg'],
                        )
                    );
                }
            }
        }

        if ($update_data['adjust_amount'] < 0) {//少补
            $out_trade_no = wddj_create_order();
            $paymentsModel = new Payments();
            Db::startTrans();
            try {
                $orderObj->save(array(
                    'state'=>'awaiting_payment',
                    'adjust_state'=>'awaiting_payment',
                ));
                $payments_data = array(
                    'order_id'=>$id,
                    'out_trade_no'=>$out_trade_no,
                    'pay_amount'=>abs($update_data['adjust_amount']),
                    'payment_type'=>'prepaid',
                    'payment_status'=>'unpaid',
                );
                $paymentsModel->data($payments_data);
                $paymentsModel->allowField(true)->save();
                Db::commit();
            } catch (ValidateException|PDOException|Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
        }


        $this->success('到达目的地成功',db('check_order')->where('out_trade_no',$orderObj->order_no)->value('id'));
    }





    /**
     * Desc 订单统计
     * Create on 2024/10/22 15:36
     * Create by wangyafang
     */
    public function statistics()
    {
        if(!$this->request->isGet()) {
            $this->error('请求类型错误');
        }
        $param = $this->request->get();
        $result = $this->validate($param,'app\api\validate\wddj\trailer\Order.statistics');
        if(true !== $result){
            // 验证失败 输出错误信息
            $this->error($result);
        }
        $start_date = $param['start_date']. '00:00:01';
        $end_date = $param['end_date'].' 23:59:59';


        $incomeExpenditureModel = new \app\api\model\wddj\trailer\IncomeExpenditure();
        $where['driver_id'] = array('eq',$this->driverObj->id);
        $where['wechat_id'] = array('eq',$this->driverObj->wechat_id);
        $where['group_type'] = array('eq','1');
        $total_income = $incomeExpenditureModel
            ->where($where)
            ->whereTime('createtime','between',[$start_date, $end_date])
            ->where('operate','1')
            ->sum('amount');

        $already_withdrawn = $incomeExpenditureModel
            ->where($where)
            ->whereTime('createtime','between',[$start_date, $end_date])
            ->where('operate','2')
            ->sum('amount');//已提现

        $driverWithdrawalDataQuery = \app\api\model\wddj\trailer\Withdrawal::getWithdrawalData($this->driverObj);

        $acceptance_number = (new \app\api\model\wddj\trailer\Order())
            ->where('state','in',['accepted','in_progress','adjusting','refunded','awaiting_payment','completed'])
            ->where('driver_id',$this->driverObj->id)
            ->where('driver_wechat_id',$this->driverObj->wechat_id)
            ->whereTime('acceptance_time', 'between',[$start_date, $end_date])
            ->count();

        $data = array(
            'total_income'=>$total_income,
            'already_withdrawn'=>$already_withdrawn,//已提现
            'pending_withdrawal'=>$driverWithdrawalDataQuery['pending_withdrawal'],//待提现
            'acceptance_number'=>$acceptance_number,
        );
        $this->success('请求成功',$data);

    }


}



 